#pragma once
#include <string>
#include <vector>
#include <list>
#include <mymutex.hxx>
#include <mythread.hxx>
#include <ctime>

#include "auto.hxx"	// DMFun

using namespace std;

class Task;
class FileLog;

class ProxyManager	:	public Thread
{
public:
	////////////////////////////////////////////////////////////////////////////
	///////////////Constructor and Destructor///////////////////////////////////
	ProxyManager(DMFun f, Task* seed, FileLog* filelog=0);
	~ProxyManager();

	void Shutdown(void);
	string GetProxy(void);
	//bool GetValidProxies(std::vector<std::string>& proxies) const;

	void InvalidProxy(const string& proxy);

protected:
	virtual void Execute(Thread::Arg arg);

private:

	int LoadProxies(string& errmsg);
	bool ValidateProxies(void);
	bool AddProxy(const string& proxy);
	string GetProxyImp(void);

	typedef enum
	{
		PROXY_STATUS_INVALID,
		PROXY_STATUS_FREE,
		PROXY_STATUS_VALIDATING,
		PROXY_STATUS_VALID
	}ProxyStatus;
	class Tester : public Thread
	{
	public:
		Tester(void* proxyinfo, Task* seed, DMFun f, FileLog* filelog=NULL);

	protected:
		virtual void Execute(Thread::Arg arg);

		Task* seed;
		DMFun DisplayMsg;
		FileLog* _filelog;
	};
	typedef struct
	{
		mutable Mutex* lock;
		string ip;
		string country;
		string type;
		int latency;
		ProxyStatus status;
		int refcount;
		bool isreported;
		bool shutdowned;
		Tester* tester;
	}tProxyInfo;

	void DumpProxies(void);
	static bool compare_by_latency(const tProxyInfo* info1, const tProxyInfo* info2);

	std::list<tProxyInfo*> proxies;
	mutable Mutex proxiesInUse;

	Task* seed;

	DMFun DisplayMsg;
	bool isshutdown_requested;
	FileLog* _filelog;
};